package com.gzhryc.common.data;

import com.gzhryc.common.ClassTools;
import com.gzhryc.common.StringTools;
import com.gzhryc.common.data.annotation.IsEmail;
import com.gzhryc.common.data.annotation.IsIP;
import com.gzhryc.common.data.annotation.IsPhone;
import com.gzhryc.common.data.annotation.Valid;
import com.gzhryc.common.exceptions.CheckErrorException;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Field;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 数据验证工具类
 * @author 张浩
 * @version 1.3.2
 */
public class ValidateTools {
		
	public static void isValid(Map<String,String> errors,Object value,String name,Valid valid){
		if(StringUtils.isNotBlank(valid.pattern())){
			String errorMsg = valid.errorMsg();
			if(StringUtils.isBlank(errorMsg)) {
				if(StringUtils.isNotBlank(valid.name())) {
					errorMsg = valid.name()+"格式错误";
				}
			}
			if(StringUtils.isNotBlank(errorMsg)){
				isPattern(errors,value,valid.pattern(),name,errorMsg);
			}else{
				isPattern(errors,value,valid.pattern(),name);
			}
		}else if(valid.notNull()){
			String errorMsg = valid.errorMsg();
			if(StringUtils.isBlank(errorMsg)) {
				if(StringUtils.isNotBlank(valid.name())) {
					errorMsg = valid.name()+"必填";
				}
			}
			if(StringUtils.isNotBlank(errorMsg)) {
				isNotNull(errors,value,name,errorMsg);
			}else {
				isNotNull(errors,value,name);
			}
		}else if(valid.isNumber()){
			String errorMsg = valid.errorMsg();
			if(StringUtils.isBlank(errorMsg)) {
				if(StringUtils.isNotBlank(valid.name())) {
					errorMsg = valid.name()+"必须是数字";
				}
			}
			if(StringUtils.isNotBlank(errorMsg)) {
				isNumber(errors,value,name,errorMsg);
			}else {
				isNumber(errors,value,name);
			}
		}else {
			String errorMsg = valid.errorMsg();
			if(valid.minLength() > 0 && valid.maxLength() > 0){
				if(StringUtils.isBlank(errorMsg)) {
					if(StringUtils.isNotBlank(valid.name())) {
						errorMsg = valid.name()+"长度必须在"+valid.minLength()+"和"+valid.maxLength()+"之间";
					}
				}
				if(StringUtils.isNotBlank(errorMsg)) {
					isLength(errors,value,valid.minLength(),valid.maxLength(),name,errorMsg);
				}else {
					isLength(errors,value,valid.minLength(),valid.maxLength(),name);
				}
			}else if(valid.minLength() > 0) {
				if(StringUtils.isBlank(errorMsg)) {
					if(StringUtils.isNotBlank(valid.name())) {
						errorMsg = valid.name()+"必须大于"+valid.minLength();
					}
				}
				if(StringUtils.isNotBlank(errorMsg)) {
					isMaxLength(errors,value,valid.minLength(),name,errorMsg);
				}else {
					isMaxLength(errors,value,valid.minLength(),name);
				}
			}else if(valid.maxLength() > 0) {
				if(StringUtils.isBlank(errorMsg)) {
					if(StringUtils.isNotBlank(valid.name())) {
						errorMsg = valid.name()+"必须小于"+valid.maxLength();
					}
				}
				if(StringUtils.isNotBlank(errorMsg)) {
					isMinLength(errors,value,valid.minLength(),name,errorMsg);
				}else {
					isMinLength(errors,value,valid.minLength(),name);
				}
			}
		}
	}
	
	public static void isPattern(Map<String,String> errors,Object value,String patStr,String... args){
		Pattern pat = Pattern.compile(patStr);
		if(value == null || !pat.matcher(value.toString()).find()){
			if(args.length == 1){
				errors.put(args[0], "请输入正确的值");
			}else if(args.length == 2){
				//以后添加国际化
				errors.put(args[0], args[1]);
			}else{
				//@需要特殊处理
			}
		}
	}
	
	public static void isEmail(Map<String,String> errors,Object value,String... args){
		if(!isEmail(value)){
			if(args.length == 1){
				errors.put(args[0], "请输入正确的电子邮箱");
			}else if(args.length == 2){
				//以后添加国际化
				errors.put(args[0], args[1]);
			}else{
				//@需要特殊处理
			}
		}
	}
	
	/**
	 * 是否是电子邮件
	 * @param value
	 * @return
	 */
	public static boolean isEmail(Object value){
		if(value != null && ValidPattern.PATTERN_EMAIL.matcher(value.toString()).find()){
			return true;
		}
		return false;
	}
	
	/**
	 * 是否是IP地址
	 * @param errors
	 * @param value
	 * @param args
	 */
	public static void isIpAddress(Map<String,String> errors,Object value,String... args){
		if(!isIpAddress(value)){
			if(args.length == 1){
				errors.put(args[0], "请输入正确的IP地址");
			}else if(args.length == 2){
				//以后添加国际化
				errors.put(args[0], args[1]);
			}else{
				//@需要特殊处理
			}
		}
	}
	
	public static boolean isIpAddress(Object value){
		if(value != null && ValidPattern.PATTERN_IP.matcher(value.toString()).find()){
			return true;
		}
		return false;
	}
	
	public static void isPhone(Map<String,String> errors,Object value,String... args){
		if(!isPhone(value)){
			if(args.length == 1){
				errors.put(args[0], "请输入正确的手机号");
			}else if(args.length == 2){
				//以后添加国际化
				errors.put(args[0], args[1]);
			}else{
				//@需要特殊处理
			}
		}
	}
	
	/**
	 * 是否是手机号
	 * @param value
	 * @return
	 */
	public static boolean isPhone(Object value){
		//默认中国手机号
		if(value != null && ValidPattern.PATTERN_PHONE.matcher(value.toString()).find()){
			return true;
		}
		return false;
	}
	
	public static boolean isPhone(Object value,String phoneCode){
		if(StringUtils.isBlank(phoneCode) || "+86".equals(phoneCode)) {
			if(value != null && ValidPattern.PATTERN_PHONE.matcher(value.toString()).find()){
				return true;
			}
		}else{
			if(value != null && ValidPattern.PATTERN_INTERNATIONAL_PHONE.matcher(value.toString()).find()){
				return true;
			}
		}
		return false;
	}
	
	public static void isNumber(Map<String,String> errors,Object value,String... args){
		if(!isNumber(value)){
			if(args.length == 1){
				errors.put(args[0], "请输入正确的数字");
			}else if(args.length == 2){
				//以后添加国际化
				errors.put(args[0], args[1]);
			}else{
				//@需要特殊处理
			}
		}
	}
	
	/**
	 * 是否是数字
	 * @param value
	 * @return
	 */
	public static boolean isNumber(Object value){
		if(value != null && ValidPattern.PATTERN_NUMBER.matcher(value.toString()).find()){
			return true;
		}
		return false;
	}
	
	public static void isNotNull(Map<String,String> errors,Object value,String... args){
		if(value == null || StringUtils.isBlank(value.toString())){
			if(args.length == 1){
				errors.put(args[0], args[0]+"不能为空");
				//以后添加国际化
			}else if(args.length == 2){
				errors.put(args[0], args[1]);
			}else{
				//@需要特殊处理
			}
		}
	}
	
	public static void isMinLength(Map<String,String> errors,Object value,int length,String... args){
		if(value == null || value.toString().length() < length){
			if(args.length == 1){
				errors.put(args[0], args[0]+"长度必须大于"+length);
				//以后添加国际化
			}else if(args.length == 2){
				errors.put(args[0], args[1]);
			}else{
				//@需要特殊处理
			}
		}
	}
	
	public static void isMaxLength(Map<String,String> errors,Object value,int length,String... args){
		if(value != null && value.toString().length() > length){
			if(args.length == 1){
				errors.put(args[0], args[0]+"长度必须小于"+length);
			}else if(args.length == 2){
				//以后添加国际化
				errors.put(args[0], args[1]);
			}else{
				//@需要特殊处理
			}
		}
	}
	
	public static void isLength(Map<String,String> errors,Object value,int minLength,int maxLength,String... args){
		if(value == null || value.toString().length() < minLength 
				|| value.toString().length() > maxLength){
			if(args.length == 1){
				errors.put(args[0], args[0]+"长度必须在"+minLength+"和"+maxLength+"之间");
			}else if(args.length == 2){
				//以后添加国际化
				errors.put(args[0], args[1]);
			}else{
				//@需要特殊处理
			}
		}
	}
	
	/**
	 * 验证对象
	 * @param entity
	 * @throws CheckErrorException
	 */
	public static <T> void check(T entity) throws CheckErrorException{
		CheckErrorException ex = new CheckErrorException();
		Class<?> clazz = entity.getClass();
		try{
			Field[] fields = ClassTools.getDeclaredFields(clazz); //获取子父类字段
			for (Field field : fields) {
				field.setAccessible(true);
				Object value = field.get(entity);
				
				Valid valid = field.getAnnotation(Valid.class);
				if(valid != null){
					if(value == null && !valid.notNull()) {
						continue;
					}
					ValidateTools.isValid(ex.getErrors(), value, field.getName(), valid);
				}
				if(value != null) {
					IsEmail isEmail = field.getAnnotation(IsEmail.class);
					if(isEmail != null) {
						isEmail(ex.getErrors(),value,field.getName());
					}
					IsIP isIP = field.getAnnotation(IsIP.class);
					if(isIP != null) {
						isIpAddress(ex.getErrors(),value,field.getName());
					}
					IsPhone isPhone = field.getAnnotation(IsPhone.class);
					if(isPhone != null) {
						isPhone(ex.getErrors(),value,field.getName());
					}
				}
			}
			
			if(DataValidator.class.isInstance(entity)){
				((DataValidator)entity).validate(ex.getErrors());
			}
		}catch(Exception e){
			ex.getErrors().put("system", "参数错误");
		}
		
		if(ex.getErrors().size() > 0){
			ex.setEntity(entity);
			throw ex;
		}
	}
	
	public static String delHTMLTag(String htmlStr){
		if(StringTools.isNotBlank(htmlStr)) {
			String regEx_script = "<script[^>]*?>[\\s\\S]*?<\\/script>"; //定义script的正则表达式
			String regEx_style = "<style[^>]*?>[\\s\\S]*?<\\/style>"; //定义style的正则表达式
			String regEx_html = "<[^>]+>"; //定义HTML标签的正则表达式

			Pattern p_script = Pattern.compile(regEx_script, Pattern.CASE_INSENSITIVE);
			Matcher m_script = p_script.matcher(htmlStr);
			htmlStr = m_script.replaceAll(""); //过滤script标签

			Pattern p_style = Pattern.compile(regEx_style, Pattern.CASE_INSENSITIVE);
			Matcher m_style = p_style.matcher(htmlStr);
			htmlStr = m_style.replaceAll(""); //过滤style标签

			Pattern p_html = Pattern.compile(regEx_html, Pattern.CASE_INSENSITIVE);
			Matcher m_html = p_html.matcher(htmlStr);
			htmlStr = m_html.replaceAll(""); //过滤html标签

			return htmlStr.trim(); //返回文本字符串
		}
		return htmlStr;
	}
	
	public static boolean checkPwd(String str) {
		boolean haveDigit = false;// 定义一个boolean值，用来表示是否包含数字
		boolean haveLetter = false;// 定义一个boolean值，用来表示是否包含字母
		for (int i = 0; i < str.length(); i++) {
			if (Character.isDigit(str.charAt(i))) { // 用char包装类中的判断数字的方法判断每一个字符
				haveDigit = true;
			} else if (Character.isLetter(str.charAt(i))) { // 用char包装类中的判断字母的方法判断每一个字符
				haveLetter = true;
			}
		}
		String regex = "^[a-zA-Z0-9]{6,16}$";
		boolean isRight = haveDigit && haveLetter && str.matches(regex) && checkRepeatSubstring(str,3);
		return isRight;
	}

	/**
	 * 不能有相同长的子串重复
	 * @param str
	 * @return
	 */
	public static boolean checkRepeatSubstring(String str,int num) {
		for (int i = 0; i < str.length() - num; i++) {
			String s = str.substring(i, i + num);
			int index = i + num;
			if(index + num <= str.length()) {
				String tempStr = str.substring(index, index + num);
				if (tempStr.equals(s)) {
					return false;
				}
			}
		}
		return true;
	}

	public static boolean checkSimpleNumber(String str) {
		if(str.length() > 5){
			if(str.contains("12345")){
				return false;
			}else if(str.contains("23456")){
				return false;
			}else if(str.contains("34567")){
				return false;
			}else if(str.contains("45678")){
				return false;
			}else if(str.contains("56789")){
				return false;
			}
		}
		return true;
	}

	/**
	 * 加密部分手机号
	 * @param phone
	 * @return
	 */
	public static String encryptionPhone(String phone){
		if(phone.length() > 10){
			String first = phone.substring(0,3);
			String last = phone.substring(phone.length() - 4);
			return first + "***" + last;
		}
		return phone;
	}

	/**
	 * 加密部分银行卡号
	 * @param cardNo
	 * @return
	 */
	public static String encryptionCardNo(String cardNo) {
		if (StringUtils.isBlank(cardNo)) {
			return cardNo;
		}
		int length = cardNo.length();
		int beforeLength = 4;
		int afterLength = 4;
		String replaceSymbol = "*";
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < length; i++) {
			if (i < beforeLength || i >= (length - afterLength)) {
				sb.append(cardNo.charAt(i));
			} else {
				sb.append(replaceSymbol);
			}
		}

		return sb.toString();
	}


	/**
	 * 是否是简单字符串，数字 + 字母 + 下划线
	 * @param simpleStr
	 * @return
	 */
	public static boolean simpleString(String simpleStr){
		if(StringTools.isNotBlank(simpleStr)){
			return ValidPattern.PATTERN_SIMPLE_STR.matcher(simpleStr).find();
		}
		return false;
	}
}
